/**
 * Copyright 2020 jianggujin (www.jianggujin.com).
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.jianggujin.dbfly.mybatis.dialect.page;

import java.util.Map;
import java.util.Map.Entry;

import org.apache.ibatis.scripting.xmltags.DynamicContext;
import org.apache.ibatis.scripting.xmltags.MixedSqlNode;
import org.apache.ibatis.scripting.xmltags.SqlNode;

import com.jianggujin.dbfly.mybatis.entity.JPage;
import com.jianggujin.dbfly.util.JDBFlyException;
import com.jianggujin.dbfly.util.JStringUtils;

/**
 * 分页节点抽象实现
 * 
 * @author jianggujin
 *
 */
public class JAbstractPageSqlNode implements SqlNode {
    public static final String ROOT_PAGE = "$root";
    public static final String DYNAMIC_PAGE_SIZE_KEY = "__PageSize__";
    public static final String DYNAMIC_START_ROW_KEY = "__StartRow__";
    public static final String DYNAMIC_END_ROW_KEY = "__EndRow__";
    public static final String STATIC_PAGE_SIZE_KEY = "pageSize";
    public static final String STATIC_START_ROW_KEY = "startRow";
    public static final String STATIC_END_ROW_KEY = "endRow";
    protected final boolean dynamicParse;
    private final MixedSqlNode mixedSqlNode;
    protected final String name;
    protected final String startRow;
    protected final String endRow;
    protected final String pageSize;

    public JAbstractPageSqlNode(MixedSqlNode mixedSqlNode, String name, String startRow, String endRow,
            String pageSize) {
        this.mixedSqlNode = mixedSqlNode;
        this.dynamicParse = JStringUtils.isEmpty(name);
        this.name = ROOT_PAGE.equals(name) ? DynamicContext.PARAMETER_OBJECT_KEY : name;
        this.startRow = JStringUtils.isEmpty(startRow) ? STATIC_START_ROW_KEY : startRow;
        this.endRow = JStringUtils.isEmpty(endRow) ? STATIC_END_ROW_KEY : endRow;
        this.pageSize = JStringUtils.isEmpty(startRow) ? STATIC_PAGE_SIZE_KEY : pageSize;
    }

    @Override
    public boolean apply(DynamicContext context) {
        if (this.dynamicParse) {
            JPage page = this.findPage(context);
            if (page == null) {
                throw new JDBFlyException("无法获取分页对象，可尝试通过name属性绑定");
            }
            this.bindPage(context, page);
        }
        this.applyNode(context);
        return true;
    }

    /**
     * 查找分页对象
     * 
     * @param context
     * @return
     */
    protected JPage findPage(DynamicContext context) {
        Object parameter = context.getBindings().get(DynamicContext.PARAMETER_OBJECT_KEY);
        if (parameter instanceof JPage) {
            return (JPage) parameter;
        } else if (parameter instanceof Map<?, ?>) {
            Map<?, ?> map = (Map<?, ?>) parameter;
            for (Entry<?, ?> entry : map.entrySet()) {
                if (entry.getValue() instanceof JPage) {
                    return (JPage) parameter;
                }
            }
        }
        return null;
    }

    /**
     * 绑定分页数据
     * 
     * @param context
     * @param page
     */
    protected void bindPage(DynamicContext context, JPage page) {
        context.bind(DYNAMIC_START_ROW_KEY, page.getStartRow());
        context.bind(DYNAMIC_PAGE_SIZE_KEY, page.getPageSize());
        context.bind(DYNAMIC_END_ROW_KEY, page.getEndRow());
    }

    protected void applyNode(DynamicContext context) {
        mixedSqlNode.apply(context);
    }
}